package common.activiti.web.action;

import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.task.Attachment;
import org.activiti.engine.task.DelegationState;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import common.hibernate.vo.Page;
import common.security.web.util.SecurityUtil;
import common.web.action.CommonAction;
import common.web.vo.Result;

/**
 * 运行中的执行实例Execution
 */
@RestController
@RequestMapping("/bpm/task")
public class TaskController extends CommonAction {

	@Autowired
	RuntimeService runtimeService;

	@Autowired
	RepositoryService repositoryService;

	@Autowired
	TaskService taskService;

	@Autowired
	IdentityService identityService;

	@Autowired
	FormService formService;

	@Autowired
	HistoryService historyService;

	/**
	 * 读取启动流程的表单字段
	 */
	@RequestMapping(value = "list")
	public Result todoTasks(@RequestBody JSONObject json) throws Exception {

		String taskName = json.getString("taskName");
		Page<Task> page = new Page<Task>();
		page.setPageSize(super.getPageSize(json));
		page.setCurrentPage(super.getPageNumber(json));
		String userId = SecurityUtil.getUserName();

		NativeTaskQuery nativeTaskQuery = taskService.createNativeTaskQuery();

		/*
		 * 过滤条件
		 */
		String filters = "";
		if (StringUtils.isNotBlank(taskName)) {
			filters += " and RES.NAME_ like #{taskName}";
			nativeTaskQuery.parameter("taskName", "%" + taskName + "%");
		}

		// 当前人在候选人或者候选组范围之内
		String sql = "select distinct RES.* from ACT_RU_TASK RES left join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ WHERE SUSPENSION_STATE_ = '1' and "
				+ " ( RES.ASSIGNEE_ = #{userId}"
				+ " or (RES.ASSIGNEE_ is null  and ( I.USER_ID_ = #{userId} or I.GROUP_ID_ IN (select G.GROUP_ID_ from ACT_ID_MEMBERSHIP G where G.USER_ID_ = #{userId} ) )"
				+ ") )" + filters + " order by RES.CREATE_TIME_ desc";

		nativeTaskQuery.sql(sql).parameter("userId", userId);
		List<Task> tasks = nativeTaskQuery.listPage(page.getStart(), page.getPageSize());

		page.setRows(tasks);
		page.setTotal(Long.valueOf(nativeTaskQuery.sql("select count(*) from (" + sql + ") t").count()).intValue());

		// 从5.16版本开始可以使用以下方式
		/*
		 * TaskQuery taskQuery =
		 * taskService.createTaskQuery().taskCandidateOrAssigned(user.getId());
		 * page.setTotalCount(taskQuery.count());
		 * page.setResult(taskQuery.list()); mav.addObject("tasks", tasks);
		 */

		return Result.createPageResult(page);
	}

	/**
	 * 签收任务
	 */
	@RequestMapping(value = "claim/{id}")
	public Result claim(@PathVariable("id") String taskId) {
		String userId = SecurityUtil.getUserName();
		taskService.claim(taskId, userId);
		Result result = Result.fail("任务已签收");
		result.setSuccess(true);
		return result;
	}

	/**
	 * 反签收任务
	 */
	@RequestMapping(value = "unclaim/{id}")
	public Result unclaim(@PathVariable("id") String taskId) {
		// 反签收条件过滤
		List<IdentityLink> links = taskService.getIdentityLinksForTask(taskId);
		Result result = Result.fail("该任务不允许反签收！");
		result.setSuccess(true);
		for (IdentityLink identityLink : links) {
			// 如果一个任务有相关的候选人、组就可以反签收
			if (StringUtils.equals(IdentityLinkType.CANDIDATE, identityLink.getType())) {
				taskService.claim(taskId, null);
				result.setMsg("任务已反签收");
				break;
			}
		}
		return result;
	}

	/**
	 * 任务委派
	 *
	 * @param taskId
	 * @param delegateUserId
	 */
	@RequestMapping("delegate/{taskId}")
	public Result delegate(@PathVariable("taskId") String taskId, @RequestBody JSONObject json) {
		String delegateUserId = json.getString("delegateUserId");
		if(StringUtils.isBlank(delegateUserId)) {
			return Result.fail("委派人不能为空");
		}
		taskService.delegateTask(taskId, delegateUserId);
		return Result.SUCCESS;
	}

	/**
	 * 读取用户任务的表单字段
	 */
	@RequestMapping(value = "getform/{taskId}")
	public Result readTaskForm(@PathVariable("taskId") String taskId) throws Exception {
		TaskFormData taskFormData = formService.getTaskFormData(taskId);
		Task task = null;

		Map<Object, Object> reMap = new HashMap<Object, Object>();
		Result result = Result.createResult(null);
		boolean hasUsers = false;

		// 外置表单
		if (taskFormData != null && taskFormData.getFormKey() != null) {
			Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
			task = taskService.createTaskQuery().taskId(taskId).singleResult();
			result.addMap("taskFormData", renderedTaskForm);
			result.addMap("hasFormKey", true);
		} else if (taskFormData != null) { // 动态表单
			result.addMap("taskFormData", taskFormData);

			List<FormProperty> formProperties = taskFormData.getFormProperties();
			for (FormProperty fp : formProperties) {
				Map<String, Object> infoMap = new HashMap<String, Object>();
				reMap.put(fp.getId(), infoMap);
				String[] keys = { "datePattern", "values" };
				if ("users".equals(fp.getType().getName())) {
					hasUsers = true;
				}
				for (String key : keys) {
					Object information = fp.getType().getInformation(key);
					infoMap.put(key, information);
				}
			}
			task = taskFormData.getTask();

			result.addMap("formPropertiesInformation", reMap);
		} else { // 手动创建的任务（包括子任务）
			task = taskService.createTaskQuery().taskId(taskId).singleResult();
			result.addMap("manualTask", true);
		}

		if (hasUsers) {
			result.addMap("hasUsers", hasUsers);
		}

		result.addMap("task", task);

		// 读取任务参与人列表
		List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(taskId);
		result.addMap("identityLinksForTask", identityLinksForTask);

		// 读取所有人员
		List<User> users = identityService.createUserQuery().list();
		result.addMap("users", users);

		// 读取所有组
		List<Group> groups = identityService.createGroupQuery().list();
		result.addMap("groups", groups);

		// 读取子任务
		List<HistoricTaskInstance> subTasks = historyService.createHistoricTaskInstanceQuery().taskParentTaskId(taskId)
				.list();
		result.addMap("subTasks", subTasks);

		// 读取上级任务
		if (task != null && task.getParentTaskId() != null) {
			HistoricTaskInstance parentTask = historyService.createHistoricTaskInstanceQuery()
					.taskId(task.getParentTaskId()).singleResult();
			result.addMap("parentTask", parentTask);
		}

		// 读取附件
		List<Attachment> attachments = null;
		if (task.getTaskDefinitionKey() != null) {
			attachments = taskService.getTaskAttachments(taskId);
		} else {
			attachments = taskService.getProcessInstanceAttachments(task.getProcessInstanceId());
		}
		result.addMap("attachments", attachments);

		return result;
	}
	
	/**
     * 读取启动流程的表单字段
     */
    @RequestMapping(value = "complete/{taskId}")
    public Result completeTask(@PathVariable("taskId") String taskId, @RequestBody JSONObject json) throws Exception {

    	JSONObject fromValues = json.getJSONObject("formData");
    	
        // 设置当前操作人，对于调用活动可以获取到当前操作人
        String currentUserId = SecurityUtil.getUserName();
        identityService.setAuthenticatedUserId(currentUserId);

        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 如果任务的流程定义任务Key为空则认为是手动创建的任务
        if (StringUtils.isBlank(task.getTaskDefinitionKey())) {
            taskService.complete(taskId);
            return Result.SUCCESS;
        }

        // 权限检查-任务的办理人和当前人不一致不能完成任务
        if (!task.getAssignee().equals(currentUserId)) {
            return Result.fail("没有权限，不能完成该任务！");
        }

        // 单独处理被委派的任务
        if (task.getDelegationState() == DelegationState.PENDING) {
            taskService.resolveTask(taskId);
            return Result.SUCCESS;
        }

        TaskFormData taskFormData = formService.getTaskFormData(taskId);
        String formKey = taskFormData.getFormKey();
        // 从请求中获取表单字段的值
        
        Map<String, String> formValues = new HashMap<String, String>();

        if (StringUtils.isNotBlank(formKey)) { // formkey表单
        	Set<Map.Entry<String, Object>> entrySet = fromValues.entrySet();
            for (Entry<String, Object> entry : entrySet) {
                String key = entry.getKey();
                String v = null;
                Object value = fromValues.get(key);
                if(value instanceof JSONArray) {
            		v = StringUtils.join(value, ",");
            	} else if(null != value) {
            		v = value.toString();
            	}
                formValues.put(key, v);
            }
        } else { // 动态表单
        	List<FormProperty> formProperties = taskFormData.getFormProperties();
            for (FormProperty formProperty : formProperties) {
            	if (formProperty.isWritable() && !"javascript".equals(formProperty.getType().getName())) {
					String v = null;
					Object value = fromValues.get(formProperty.getId());
					if (value instanceof JSONArray) {
						v = StringUtils.join(((JSONArray) value).iterator(), ",");
					} else if(null != value) {
						v = value.toString();
					}
					formValues.put(formProperty.getId(), v);
				}
            
            }
        }
        formService.submitTaskFormData(taskId, formValues);
        return Result.SUCCESS;
    }
    
    /**
     * 更改任务属性
     *
     * @throws ParseException
     */
    @RequestMapping("property/{taskId}")
    public Result changeTaskProperty(@PathVariable("taskId") String taskId, @RequestBody JSONObject json)
            throws ParseException {
    	String propertyName = json.getString("propertyName");
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 更改到期日
        if (StringUtils.equals(propertyName, "dueDate")) {
            task.setDueDate(json.getDate("value"));
            taskService.saveTask(task);
        } else if (StringUtils.equals(propertyName, "priority")) {
            // 更改任务优先级
            task.setPriority(json.getInteger("value"));
            taskService.saveTask(task);
        } else if (StringUtils.equals(propertyName, "owner")) {
            // 更改拥有人
            task.setOwner(json.getString("value"));
            taskService.saveTask(task);
        } else if (StringUtils.equals(propertyName, "assignee")) {
            // 更改办理人
            task.setAssignee(json.getString("value"));
            taskService.saveTask(task);
        } else {
            return Result.fail("不支持[" + propertyName + "]属性！");
        }
        return Result.SUCCESS;
    }

}
